package com.shrct.businessprocess.project.impl;

import com.google.common.base.Objects;
import com.google.common.collect.Iterables;
import com.shrct.businessprocess.budget.IHasACTEffectBudget;
import com.shrct.businessprocess.budget.RCBudget;
import com.shrct.businessprocess.budget.RCCost4ACTItem;
import com.shrct.businessprocess.budget.RCCost4RemainItem;
import com.shrct.businessprocess.budget.RCCostBreakDown;
import com.shrct.businessprocess.project.RCActualCostReport;
import com.shrct.businessprocess.project.RCActualCostReportItem;
import com.shrct.businessprocess.project.RCCost4ACTItemSnap;
import com.shrct.businessprocess.project.RCCost4RemainItemSnap;
import com.shrct.businessprocess.project.RCProject;
import com.shrct.businessprocess.project.RCProjectSummaryInfo;
import com.shrct.businessprocess.project.RCProjectTypeExtension;
import com.shrct.businessprocess.project.impl.RCActualCostReportItemImpl;
import com.shrct.businessprocess.project.impl.RCProjectImpl;
import com.shrct.businessprocess.project.proxy.RCActualCostReportProxy;
import edu.fudan.mylang.common.NumberExtensions;
import edu.fudan.mylang.pf.BaseModelObject;
import edu.fudan.mylang.pf.IObjectFactory;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import javax.persistence.AssociationOverrides;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.eclipse.xtext.xbase.lib.DoubleExtensions;
import org.eclipse.xtext.xbase.lib.Functions.Function1;
import org.eclipse.xtext.xbase.lib.Functions.Function2;
import org.eclipse.xtext.xbase.lib.IterableExtensions;
import org.eclipse.xtext.xbase.lib.ObjectExtensions;
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
import org.hibernate.annotations.DiscriminatorOptions;

@Entity
@DiscriminatorValue("RCACTUALCOSTREPORT_TYPE")
@DiscriminatorOptions(force = true)
@DiscriminatorColumn(length = 64)
@Table(name = "rcactualcostreport")
public class RCActualCostReportImpl extends BaseModelObject implements RCActualCostReport {
  public RCActualCostReportImpl() {
    super();
  }
  
  public RCActualCostReportImpl(final RCProject project) {
    super();
    this.project = project;
  }
  
  @JoinColumn(name = "project_id")
  @ManyToOne(targetEntity = RCProjectImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST })
  private RCProject project;
  
  public RCProject getProject() {
    return this.project;
  }
  
  public RCActualCostReport setProject(final RCProject project) {
    this.project = project;
    return this;			
    
  }
  
  @Embedded
  @AttributeOverrides(value = { @AttributeOverride(name = "contractAmount", column = @Column(name = "summaryInfo_contractAmount") ), @AttributeOverride(name = "invoiceAmount", column = @Column(name = "summaryInfo_invoiceAmount") ), @AttributeOverride(name = "incomeAmount", column = @Column(name = "summaryInfo_incomeAmount") ), @AttributeOverride(name = "acceptAmount", column = @Column(name = "summaryInfo_acceptAmount") ), @AttributeOverride(name = "invoiceTax", column = @Column(name = "summaryInfo_invoiceTax") ), @AttributeOverride(name = "actualCost", column = @Column(name = "summaryInfo_actualCost") ), @AttributeOverride(name = "purchaseTax", column = @Column(name = "summaryInfo_purchaseTax") ), @AttributeOverride(name = "totalCost", column = @Column(name = "summaryInfo_totalCost") ), @AttributeOverride(name = "totalCostWithoutTax", column = @Column(name = "summaryInfo_totalCostWithoutTax") ), @AttributeOverride(name = "contractProfit", column = @Column(name = "summaryInfo_contractProfit") ), @AttributeOverride(name = "contractProfitAdj4Sale", column = @Column(name = "summaryInfo_contractProfitAdj4Sale") ), @AttributeOverride(name = "ggp", column = @Column(name = "summaryInfo_ggp") ), @AttributeOverride(name = "cggp", column = @Column(name = "summaryInfo_cggp") ), @AttributeOverride(name = "workaround", column = @Column(name = "summaryInfo_workaround") ) } )
  @AssociationOverrides(value = { } )
  private RCProjectSummaryInfo summaryInfo = com.shrct.businessprocess.project.RCProjectSummaryInfo.create();
  
  public RCProjectSummaryInfo getSummaryInfo() {
    return this.summaryInfo;
  }
  
  public RCActualCostReport setSummaryInfo(final RCProjectSummaryInfo summaryInfo) {
    this.summaryInfo = summaryInfo;
    return this;			
    
  }
  
  @JoinColumn(name = "prevReport_id")
  @ManyToOne(targetEntity = RCActualCostReportImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST })
  private RCActualCostReport prevReport;
  
  public RCActualCostReport getPrevReport() {
    return this.prevReport;
  }
  
  public RCActualCostReport setPrevReport(final RCActualCostReport prevReport) {
    this.prevReport = prevReport;
    return this;			
    
  }
  
  private Boolean isFixed = Boolean.valueOf(false);
  
  public Boolean getIsFixed() {
    return this.isFixed;
  }
  
  public RCActualCostReport setIsFixed(final Boolean isFixed) {
    this.isFixed = isFixed;
    return this;			
    
  }
  
  private Date toDate;
  
  public Date getToDate() {
    return this.toDate;
  }
  
  public RCActualCostReport setToDate(final Date toDate) {
    this.toDate = toDate;
    return this;			
    
  }
  
  private Double totalContractAmount = Double.valueOf(0d);
  
  public Double getTotalContractAmount() {
    return this.totalContractAmount;
  }
  
  public RCActualCostReport setTotalContractAmount(final Double totalContractAmount) {
    this.totalContractAmount = totalContractAmount;
    return this;			
    
  }
  
  private Double totalIncomeAmount = Double.valueOf(0d);
  
  public Double getTotalIncomeAmount() {
    return this.totalIncomeAmount;
  }
  
  public RCActualCostReport setTotalIncomeAmount(final Double totalIncomeAmount) {
    this.totalIncomeAmount = totalIncomeAmount;
    return this;			
    
  }
  
  private Double totalIncomePrecent = Double.valueOf(0d);
  
  public Double getTotalIncomePrecent() {
    return this.totalIncomePrecent;
  }
  
  public RCActualCostReport setTotalIncomePrecent(final Double totalIncomePrecent) {
    this.totalIncomePrecent = totalIncomePrecent;
    return this;			
    
  }
  
  /**
   * 累计收入比例
   */
  public Double getTotalActualAmount() {
    Double _xifexpression = null;
    boolean _equals = Objects.equal(this.summaryInfo, null);
    if (_equals) {
      final Function1<RCActualCostReportItem,Double> _function = new Function1<RCActualCostReportItem,Double>() {
          public Double apply(final RCActualCostReportItem it) {
            Double _totalActualAmount = it.getTotalActualAmount();
            return _totalActualAmount;
          }
        };
      Iterable<Double> _map = IterableExtensions.<RCActualCostReportItem, Double>map(this.items, _function);
      final Function2<Double,Double,Double> _function_1 = new Function2<Double,Double,Double>() {
          public Double apply(final Double d1, final Double d2) {
            double _plus = DoubleExtensions.operator_plus(d1, d2);
            return Double.valueOf(_plus);
          }
        };
      Double _reduce = IterableExtensions.<Double>reduce(_map, _function_1);
      Double _nullsafe = NumberExtensions.nullsafe(_reduce);
      _xifexpression = _nullsafe;
    } else {
      Double _actualCost = this.summaryInfo.getActualCost();
      _xifexpression = _actualCost;
    }
    return _xifexpression;
  }
  
  public Double getTotalGrossProfit() {
    Double _totalActualAmount = this.getTotalActualAmount();
    double _minus = DoubleExtensions.operator_minus(
      this.totalIncomeAmount, _totalActualAmount);
    return Double.valueOf(_minus);
  }
  
  public Double getTotalGrossProfitRate() {
    double _xblockexpression = (double) 0;
    {
      Double _totalActualAmount = this.getTotalActualAmount();
      boolean _equals = ((_totalActualAmount).doubleValue() == 0);
      if (_equals) {
        return Double.valueOf(0d);
      }
      Double _totalGrossProfit = this.getTotalGrossProfit();
      Double _totalActualAmount_1 = this.getTotalActualAmount();
      double _divide = DoubleExtensions.operator_divide(_totalGrossProfit, _totalActualAmount_1);
      _xblockexpression = (_divide);
    }
    return Double.valueOf(_xblockexpression);
  }
  
  public Double getIncomeAmount() {
    double _xblockexpression = (double) 0;
    {
      boolean _equals = Objects.equal(this.prevReport, null);
      if (_equals) {
        return this.totalIncomeAmount;
      }
      Double _totalIncomeAmount = this.prevReport.getTotalIncomeAmount();
      double _minus = DoubleExtensions.operator_minus(
        this.totalIncomeAmount, _totalIncomeAmount);
      _xblockexpression = (_minus);
    }
    return Double.valueOf(_xblockexpression);
  }
  
  public Double getActualAmount() {
    double _xblockexpression = (double) 0;
    {
      boolean _equals = Objects.equal(this.prevReport, null);
      if (_equals) {
        return this.getTotalActualAmount();
      }
      Double _totalActualAmount = this.getTotalActualAmount();
      Double _totalActualAmount_1 = this.prevReport.getTotalActualAmount();
      double _minus = DoubleExtensions.operator_minus(_totalActualAmount, _totalActualAmount_1);
      _xblockexpression = (_minus);
    }
    return Double.valueOf(_xblockexpression);
  }
  
  public Double getGrossProfit() {
    Double _incomeAmount = this.getIncomeAmount();
    Double _actualAmount = this.getActualAmount();
    double _minus = DoubleExtensions.operator_minus(_incomeAmount, _actualAmount);
    return Double.valueOf(_minus);
  }
  
  @OneToMany(targetEntity = RCActualCostReportItemImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE }, mappedBy = "report")
  private Collection<RCActualCostReportItem> items = new java.util.ArrayList<com.shrct.businessprocess.project.RCActualCostReportItem>();;
  
  public Collection<RCActualCostReportItem> getItems() {
    return this.items;
  }
  
  public RCActualCostReportItem createAndAddtoItems() {
    getItems().size();
    com.shrct.businessprocess.project.RCActualCostReportItem rCActualCostReportItem = new com.shrct.businessprocess.project.impl.RCActualCostReportItemImpl(this);
    getObjectFactory().create(rCActualCostReportItem);
    getItems().add(rCActualCostReportItem);
    return rCActualCostReportItem;
    
  }
  
  public RCActualCostReportItem createAndAddtoItems(final Procedure1<RCActualCostReportItem> updater) {
    getItems().size();
    com.shrct.businessprocess.project.RCActualCostReportItem rCActualCostReportItem = new com.shrct.businessprocess.project.impl.RCActualCostReportItemImpl(this);
    getObjectFactory().create(rCActualCostReportItem);
    getItems().add(rCActualCostReportItem);
    return rCActualCostReportItem;
    
  }
  
  public RCActualCostReport removeAllItems() {
    for(RCActualCostReportItem obj : this.items){
    	getObjectFactory().delete(obj);
    }
    this.items.clear();
    return this;	
    
  }
  
  public RCActualCostReport removeFromItems(final RCActualCostReportItem rCActualCostReportItem) {
    this.items.remove(rCActualCostReportItem);
    getObjectFactory().delete(rCActualCostReportItem);
    return this;
    
  }
  
  public Collection<RCCost4ACTItemSnap> getAllCost4ACTItemSnaps() {
    final Function1<RCActualCostReportItem,Collection<RCCost4ACTItemSnap>> _function = new Function1<RCActualCostReportItem,Collection<RCCost4ACTItemSnap>>() {
        public Collection<RCCost4ACTItemSnap> apply(final RCActualCostReportItem it) {
          Collection<RCCost4ACTItemSnap> _cost4ActItemSnaps = it.getCost4ActItemSnaps();
          return _cost4ActItemSnaps;
        }
      };
    Iterable<Collection<RCCost4ACTItemSnap>> _map = IterableExtensions.<RCActualCostReportItem, Collection<RCCost4ACTItemSnap>>map(this.items, _function);
    Iterable<RCCost4ACTItemSnap> _flatten = Iterables.<RCCost4ACTItemSnap>concat(_map);
    List<RCCost4ACTItemSnap> _list = IterableExtensions.<RCCost4ACTItemSnap>toList(_flatten);
    return _list;
  }
  
  public Collection<RCCost4RemainItemSnap> getAllCost4RemainItemSnaps() {
    final Function1<RCActualCostReportItem,Collection<RCCost4RemainItemSnap>> _function = new Function1<RCActualCostReportItem,Collection<RCCost4RemainItemSnap>>() {
        public Collection<RCCost4RemainItemSnap> apply(final RCActualCostReportItem it) {
          Collection<RCCost4RemainItemSnap> _cost4RemainItemSnaps = it.getCost4RemainItemSnaps();
          return _cost4RemainItemSnaps;
        }
      };
    Iterable<Collection<RCCost4RemainItemSnap>> _map = IterableExtensions.<RCActualCostReportItem, Collection<RCCost4RemainItemSnap>>map(this.items, _function);
    Iterable<RCCost4RemainItemSnap> _flatten = Iterables.<RCCost4RemainItemSnap>concat(_map);
    final Function1<RCCost4RemainItemSnap,Boolean> _function_1 = new Function1<RCCost4RemainItemSnap,Boolean>() {
        public Boolean apply(final RCCost4RemainItemSnap it) {
          Double _amount = it.getAmount();
          boolean _notEquals = ((_amount).doubleValue() != 0);
          return Boolean.valueOf(_notEquals);
        }
      };
    Iterable<RCCost4RemainItemSnap> _filter = IterableExtensions.<RCCost4RemainItemSnap>filter(_flatten, _function_1);
    List<RCCost4RemainItemSnap> _list = IterableExtensions.<RCCost4RemainItemSnap>toList(_filter);
    return _list;
  }
  
  public void performCalculate() {
    RCProjectSummaryInfo _rCProjectSummaryInfo = new RCProjectSummaryInfo();
    final Procedure1<RCProjectSummaryInfo> _function = new Procedure1<RCProjectSummaryInfo>() {
        public void apply(final RCProjectSummaryInfo it) {
          it.performUpdate(RCActualCostReportImpl.this.project, RCActualCostReportImpl.this);
        }
      };
    RCProjectSummaryInfo _doubleArrow = ObjectExtensions.<RCProjectSummaryInfo>operator_doubleArrow(_rCProjectSummaryInfo, _function);
    this.summaryInfo = _doubleArrow;
    Double _contractAmount = this.summaryInfo.getContractAmount();
    this.totalContractAmount = _contractAmount;
    RCProjectTypeExtension _typeExtension = this.project.getTypeExtension();
    Double _calcTotalIncome = _typeExtension.calcTotalIncome();
    this.totalIncomeAmount = _calcTotalIncome;
    RCProjectTypeExtension _typeExtension_1 = this.project.getTypeExtension();
    Double _calcPercent = _typeExtension_1.calcPercent();
    this.totalIncomePrecent = _calcPercent;
    RCCostBreakDown _cbd = this.project.getCbd();
    Collection<RCBudget> _budgets = _cbd.getBudgets();
    final Procedure1<RCBudget> _function_1 = new Procedure1<RCBudget>() {
        public void apply(final RCBudget budget) {
          RCActualCostReportItem _createAndAddtoItems = RCActualCostReportImpl.this.createAndAddtoItems();
          final Procedure1<RCActualCostReportItem> _function = new Procedure1<RCActualCostReportItem>() {
              public void apply(final RCActualCostReportItem reportItem) {
                reportItem.setBudget(budget);
                boolean _matched = false;
                if (!_matched) {
                  if (budget instanceof IHasACTEffectBudget) {
                    final IHasACTEffectBudget _iHasACTEffectBudget = (IHasACTEffectBudget)budget;
                    _matched=true;
                    Iterable<RCCost4ACTItem> _cost4ACItems = ((IHasACTEffectBudget)_iHasACTEffectBudget).getCost4ACItems();
                    final Procedure1<RCCost4ACTItem> _function = new Procedure1<RCCost4ACTItem>() {
                        public void apply(final RCCost4ACTItem item) {
                          RCCost4ACTItemSnap _createAndAddtoCost4ActItemSnaps = reportItem.createAndAddtoCost4ActItemSnaps();
                          final Procedure1<RCCost4ACTItemSnap> _function = new Procedure1<RCCost4ACTItemSnap>() {
                              public void apply(final RCCost4ACTItemSnap it) {
                                RCBudget _budget = item.getBudget();
                                it.setBudget(_budget);
                                String _title = item.getTitle();
                                it.setTitle(_title);
                                Date _date = item.getDate();
                                it.setDate(_date);
                                Double _amount = item.getAmount();
                                it.setAmount(_amount);
                                Double _taxRate = item.getTaxRate();
                                it.setTaxRate(_taxRate);
                              }
                            };
                          ObjectExtensions.<RCCost4ACTItemSnap>operator_doubleArrow(_createAndAddtoCost4ActItemSnaps, _function);
                        }
                      };
                    IterableExtensions.<RCCost4ACTItem>forEach(_cost4ACItems, _function);
                  }
                }
                Iterable<RCCost4RemainItem> _rCCost4RemainItems = budget.getRCCost4RemainItems();
                final Procedure1<RCCost4RemainItem> _function = new Procedure1<RCCost4RemainItem>() {
                    public void apply(final RCCost4RemainItem item) {
                      RCCost4RemainItemSnap _createAndAddtoCost4RemainItemSnaps = reportItem.createAndAddtoCost4RemainItemSnaps();
                      final Procedure1<RCCost4RemainItemSnap> _function = new Procedure1<RCCost4RemainItemSnap>() {
                          public void apply(final RCCost4RemainItemSnap it) {
                            RCBudget _budget = item.getBudget();
                            it.setBudget(_budget);
                            String _title = item.getTitle();
                            it.setTitle(_title);
                            Double _amount = item.getAmount();
                            it.setAmount(_amount);
                            Double _taxRate = item.getTaxRate();
                            it.setTaxRate(_taxRate);
                          }
                        };
                      ObjectExtensions.<RCCost4RemainItemSnap>operator_doubleArrow(_createAndAddtoCost4RemainItemSnaps, _function);
                    }
                  };
                IterableExtensions.<RCCost4RemainItem>forEach(_rCCost4RemainItems, _function);
                boolean _notEquals = (!Objects.equal(RCActualCostReportImpl.this.prevReport, null));
                if (_notEquals) {
                  Collection<RCActualCostReportItem> _items = RCActualCostReportImpl.this.prevReport.getItems();
                  final Function1<RCActualCostReportItem,Boolean> _function_1 = new Function1<RCActualCostReportItem,Boolean>() {
                      public Boolean apply(final RCActualCostReportItem it) {
                        RCBudget _budget = it.getBudget();
                        boolean _equals = Objects.equal(_budget, budget);
                        return Boolean.valueOf(_equals);
                      }
                    };
                  RCActualCostReportItem _findFirst = IterableExtensions.<RCActualCostReportItem>findFirst(_items, _function_1);
                  reportItem.setPrevItem(_findFirst);
                }
                reportItem.performCalculate();
              }
            };
          ObjectExtensions.<RCActualCostReportItem>operator_doubleArrow(_createAndAddtoItems, _function);
        }
      };
    IterableExtensions.<RCBudget>forEach(_budgets, _function_1);
  }
  
  public Boolean isEmptyResult() {
    boolean _and = false;
    Double _incomeAmount = this.getIncomeAmount();
    boolean _equals = ((_incomeAmount).doubleValue() == 0d);
    if (!_equals) {
      _and = false;
    } else {
      Double _actualAmount = this.getActualAmount();
      boolean _equals_1 = ((_actualAmount).doubleValue() == 0d);
      _and = (_equals && _equals_1);
    }
    return Boolean.valueOf(_and);
  }
  
  public static RCActualCostReport create(final RCProject project, final IObjectFactory objectFactory) {
    com.shrct.businessprocess.project.RCActualCostReport rCActualCostReport = new com.shrct.businessprocess.project.impl.RCActualCostReportImpl(
    	project
    );
    objectFactory.create(rCActualCostReport);
    return rCActualCostReport;			
    
  }
  
  public static RCActualCostReport createRCActualCostReportImpl(final RCProject project, final IObjectFactory objectFactory, final Procedure1<RCActualCostReport> init) {
    com.shrct.businessprocess.project.RCActualCostReport rCActualCostReport = new com.shrct.businessprocess.project.impl.RCActualCostReportImpl(
    	project
    );
    objectFactory.create(rCActualCostReport);
    init.apply(rCActualCostReport);
    
    return rCActualCostReport;			
    
  }
  
  public RCActualCostReportProxy toProxy() {
    com.shrct.businessprocess.project.proxy.RCActualCostReportProxy proxy = new com.shrct.businessprocess.project.proxy.RCActualCostReportProxy();
    proxy.setId(this.getId());
    if(this instanceof edu.fudan.mylang.pf.INamedModelObject){
    	proxy.setName(((edu.fudan.mylang.pf.INamedModelObject)this).getEntityName());
    }
    return proxy;
    
  }
}
